<template>
    <div ref="parentBoxRef" class="marquee-container" @mouseenter="pause" @mouseleave="resume">
        <span ref="contentRef" class="marquee-content" :style="{ animationDuration: aniDuration }">
            <span class="msg_item" v-for="(msg, ind) in displayMessages" :key="ind">
                {{ msg }}
            </span>
        </span>
    </div>
</template>

<script setup lang="ts">
import { ref, computed, onMounted, onBeforeUnmount } from 'vue'

interface MarqueeProps {
    messages: string | string[]
    speed?: number  // 像素/秒
    pauseOnHover?: boolean
    gap?: number    // 消息之间的间隔(px)
}

const props = withDefaults(defineProps<MarqueeProps>(), {
    speed: 100,
    pauseOnHover: true,
    gap: 40
})

const emit = defineEmits(['itemClick'])

const messageList = computed(() => {
    if (typeof props.messages === 'string') {
        return [props.messages]
    } else {
        return props.messages
    }
})

// 复制消息以实现无缝循环
const displayMessages = computed(() => {
    return [...messageList.value, ...messageList.value]
})

const contentRef = ref<HTMLElement | null>(null)
const parentBoxRef = ref<HTMLElement | null>(null)
const aniDuration = ref<string>('2s')
const isPaused = ref(false)
let animationFrameId: number | null = null

const calculateDuration = () => {
    if (!contentRef.value || !parentBoxRef.value) return

    const contentWidth = contentRef.value.scrollWidth / 2  // 因为内容被复制了一份
    const containerWidth = parentBoxRef.value.clientWidth

    // 计算基于内容宽度和速度的持续时间
    const durationFromWidth = (contentWidth + containerWidth) / props.speed

    // 最小持续时间确保动画可见
    const minDuration = messageList.value.length * 2  // 至少每个消息显示2秒
    const duration = Math.max(durationFromWidth, minDuration)

    aniDuration.value = `${duration}s`
}

const pause = () => {
    if (!isPaused.value && props.pauseOnHover) {
        isPaused.value = true
        if (contentRef.value) {
            contentRef.value.style.animationPlayState = 'paused'
        }
    }
}

const resume = () => {
    if (isPaused.value) {
        isPaused.value = false
        if (contentRef.value) {
            contentRef.value.style.animationPlayState = 'running'
        }
    }
}

const handleItemClick = (index: number) => {
    emit('itemClick', index % messageList.value.length)
}

onMounted(() => {
    calculateDuration()

    // 添加窗口大小变化监听
    const resizeObserver = new ResizeObserver(() => {
        calculateDuration()
    })

    if (parentBoxRef.value) {
        resizeObserver.observe(parentBoxRef.value)
    }

    onBeforeUnmount(() => {
        if (parentBoxRef.value) {
            resizeObserver.unobserve(parentBoxRef.value)
        }
    })
})
</script>

<style scoped>
.marquee-container {
    width: 100%;
    overflow: hidden;
    white-space: nowrap;
    box-sizing: border-box;
    position: relative;
}

.marquee-content {
    display: inline-block;
    /* padding-left: 100%; */
    animation: marquee linear infinite;
    animation-play-state: running;
    will-change: transform;
    flex-direction: column;
}

.msg_item {
    display: inline-block;
    margin-right: v-bind('props.gap + "px"');
    font-size: 14px;
    color: #212121;
    cursor: pointer;
    transition: color 0.2s;
}

.msg_item:hover {
    color: #1890ff;
}

@keyframes marquee {
    0% {
        transform: translateX(0);
    }

    100% {
        transform: translatey(-50%);
    }
}
</style>